﻿#include "CameraManageWidget.h"
#include <QFormLayout>
#include <QInputDialog>
#include <QGridLayout>
#include <QSplitter>

#pragma execution_character_set("utf-8")

CameraManageWidget::CameraManageWidget(const QString& title, QWidget *parent)
    : QGroupBox(title, parent)
{
    CameraBase::initStaticValue();
    setupUI();
    initConnection();
}

CameraManageWidget::~CameraManageWidget()
{
}

void CameraManageWidget::addCamera(CameraBase* cam)
{
    if(mMapCam.contains(cam->getName()))
        return;
    mMapCam.insert(cam->getName(), cam);
    cbboxCamList->addItem(cam->getName());
    cbboxCamList->setCurrentText(cam->getName());
    connect(this, &CameraManageWidget::sigConfigChanged, cam, &CameraBase::onConfigChanged);
    connect(this, &CameraManageWidget::sigReadCamParam, cam, &CameraBase::readConfig);
    connect(this, &CameraManageWidget::sigFrameSoftTrig, cam, &CameraBase::triggerSoftware);
    connect(cam, &CameraBase::sigConfig, this, &CameraManageWidget::onSetConfig);
    connect(cam, &CameraBase::sigStartSucceed, [&](){
        emit sigReadCamParam(cbboxCamList->currentText());
    });

    connect(cam, &CameraBase::sigImage, this, [&](const QString& camName,QImage image){
        if(cbboxCamList->currentText() == camName){
            mView->dispImage(image);
        }
    });
}

void CameraManageWidget::onSetConfig(const CameraConfig &config)
{
    if(cbboxCamList->currentText() != config.name)
        return;
    cbboxCamList->setCurrentText(config.name);
    cbboxCamBrand->setCurrentText(CameraBase::mapCameraBrand.value(config.brand));
    checkCamType(config);
    checkCamColor(config);

    QtUtils::configValueBox(spboxOffX, config.roi.offX.min, config.roi.offX.max, config.roi.offX.inc, config.roi.offX.val);
    QtUtils::configValueBox(spboxOffY, config.roi.offY.min, config.roi.offY.max, config.roi.offY.inc, config.roi.offY.val);
    QtUtils::configValueBox(spboxWidth, config.roi.width.min, config.roi.width.max, config.roi.width.inc, config.roi.width.val);
    QtUtils::configValueBox(spboxHeight, config.roi.height.min, config.roi.height.max, config.roi.height.inc, config.roi.height.val);

    chkboxReverseX->setChecked(config.trans.reverseX);;
    chkboxReverseY->setChecked(config.trans.reverseY);;

    cbboxFrameTrigMode->setCurrentIndex(config.trig.frameMode);
    QtUtils::configValueBox(spboxFrameTrigDelay, config.trig.frameDelay.min, config.trig.frameDelay.max, float(10.0), config.trig.frameDelay.val);

    cbboxExpMode->setCurrentIndex(config.bright.expMode);
    QtUtils::configValueBox(dspboxExp, config.bright.exp.min, config.bright.exp.max, float(10.0), config.bright.exp.val);
    cbboxGainMode->setCurrentIndex(config.bright.gainMode);
    QtUtils::configValueBox(dspboxGain, config.bright.gain.min, config.bright.gain.max, float(0.1), config.bright.gain.val);

    chkboxRateControl->setChecked(config.rate.rateControl);
    QtUtils::configValueBox(dspboxRate, config.rate.rate.min, config.rate.rate.max, float(1), config.rate.rate.val);
    dspboxRate->setVisible(config.rate.rateControl);
}

void CameraManageWidget::setupUI()
{
    mView = new GraphicsView();
    mView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    cbboxCamList  =new QComboBox();
    cbboxCamBrand  =new QComboBox();

    pbtnSave = new QPushButton("保存");
    pbtnRead = new QPushButton("读取");
    pbtnAdd = new QPushButton("增加");
    pbtnDelete = new QPushButton("删除");

    spboxOffX = new QSpinBox();
    spboxOffY = new QSpinBox();
    spboxWidth = new QSpinBox();
    spboxHeight = new QSpinBox();

    chkboxReverseX = new QCheckBox("镜像X");
    chkboxReverseY = new QCheckBox("镜像Y");

    cbboxFrameTrigMode = new QComboBox();
    pbtnFrameSoftTrig = new QPushButton("软触发");
    lblFrameTrigDelay = new QLabel("帧触发延时");
    spboxFrameTrigDelay = new QSpinBox();

    lblLineTrigMode = new QLabel("线触发模式");
    cbboxLineTrigMode = new QComboBox();

    lblWbMode = new QLabel("自动白平衡");
    cbboxWbMode = new QComboBox();
    lblWBR = new QLabel("白平衡-红");
    lblWBG = new QLabel("白平衡-绿");
    lblWBB = new QLabel("白平衡-蓝");
    spboxWBR = new QSpinBox();
    spboxWBG = new QSpinBox();
    spboxWBB = new QSpinBox();

    cbboxExpMode = new QComboBox();
    lblExp = new QLabel("曝光时间");
    dspboxExp = new QDoubleSpinBox();
    cbboxGainMode = new QComboBox();
    lblGain = new QLabel("增益");
    dspboxGain = new QDoubleSpinBox();

    chkboxRateControl = new QCheckBox("帧率控制");
    lblRate = new QLabel("帧率");
    dspboxRate = new QDoubleSpinBox();

    lblPreDiv = new QLabel("预除器");
    lblMul = new QLabel("乘法器");
    lblPostDiv = new QLabel("后除器");
    spboxPreDiv = new QSpinBox();
    spboxMul = new QSpinBox();
    spboxPostDiv = new QSpinBox();

    cbboxCamBrand->addItems(CameraBase::mapCameraBrand.values());
    cbboxFrameTrigMode->addItems(CameraBase::mapTrigModeStr.values());
    cbboxLineTrigMode->addItems(CameraBase::mapTrigModeStr.values());
    cbboxExpMode->addItems(CameraBase::mapExpAutoStr.values());
    cbboxGainMode->addItems(CameraBase::mapGainModeStr.values());
    cbboxWbMode->addItems(CameraBase::mapWBModeStr.values());


    QtUtils::configValueBox(spboxWBR, 0, 10000, 1, 1500);
    QtUtils::configValueBox(spboxWBG, 0, 10000, 1, 1500);
    QtUtils::configValueBox(spboxWBB, 0, 10000, 1, 1500);

    QtUtils::configValueBox(spboxPreDiv, 0, 128, 1, 1);
    QtUtils::configValueBox(spboxMul, 0, 128, 1, 1);
    QtUtils::configValueBox(spboxPostDiv, 0, 128, 1, 1);

    QtUtils::configValueBox(spboxOffX, 0, 10000, 1, 0);
    QtUtils::configValueBox(spboxOffY, 0, 10000, 1, 0);
    QtUtils::configValueBox(spboxWidth, 0, 10000, 1, 0);
    QtUtils::configValueBox(spboxHeight, 0, 10000, 1, 0);
    QtUtils::configValueBox(spboxFrameTrigDelay, 0, 10000, 1, 0);
    QtUtils::configValueBox(dspboxExp, 0.0, 10000.0, 1.0, 1000.0);
    QtUtils::configValueBox(dspboxGain, 0.0, 10000.0, 1.0, 1.0);
    QtUtils::configValueBox(dspboxRate, 0.0, 10000.0, 1.0, 10.0);

    QHBoxLayout* hLayout = new QHBoxLayout();
    this->setLayout(hLayout);
    hLayout->setMargin(0);
    hLayout->setContentsMargins(0,0,0,0);

    QSplitter* sp = new QSplitter(Qt::Horizontal);
    hLayout->addWidget(sp);

    QWidget* wgtParam = new QWidget();
    sp->addWidget(wgtParam);
    QVBoxLayout* vLayout = new QVBoxLayout();
    wgtParam->setLayout(vLayout);
    QGridLayout* gLayout = new QGridLayout();
    vLayout->addLayout(gLayout);
    vLayout->addStretch();

    sp->addWidget(mView);

    int col = 0;
    int row = -1;
    //先添加第一列
    gLayout->addWidget(pbtnAdd, ++row, col);
    gLayout->addWidget(pbtnRead, ++row, col);
    gLayout->addWidget(new QLabel("设备列表"), ++row, col);
    gLayout->addWidget(new QLabel("设备品牌"), ++row, col);
    gLayout->addWidget(new QLabel("偏移X"), ++row, col);
    gLayout->addWidget(new QLabel("偏移Y"), ++row, col);
    gLayout->addWidget(new QLabel("视野宽"), ++row, col);
    gLayout->addWidget(new QLabel("视野高"), ++row, col);
    gLayout->addWidget(chkboxReverseX, ++row, col);
    gLayout->addWidget(new QLabel("帧触发模式"), ++row, col);
    gLayout->addWidget(pbtnFrameSoftTrig, ++row, col, 1, 2);
    gLayout->addWidget(lblFrameTrigDelay, ++row, col);
    gLayout->addWidget(new QLabel("自动曝光"), ++row, col);
    gLayout->addWidget(lblExp, ++row, col);
    gLayout->addWidget(new QLabel("增益模式"), ++row, col);
    gLayout->addWidget(lblGain, ++row, col);
    gLayout->addWidget(chkboxRateControl, ++row, col, 1, 2);
    gLayout->addWidget(lblRate, ++row, col);
    gLayout->addWidget(lblWbMode, ++row, col);
    gLayout->addWidget(lblWBR, ++row, col);
    gLayout->addWidget(lblWBG, ++row, col);
    gLayout->addWidget(lblWBB, ++row, col);
    gLayout->addWidget(lblLineTrigMode, ++row, col);
    gLayout->addWidget(lblPreDiv, ++row, col);
    gLayout->addWidget(lblMul, ++row, col);
    gLayout->addWidget(lblPostDiv, ++row, col);

    ++col;
    row = -1;
    gLayout->addWidget(pbtnDelete, ++row, col);
    gLayout->addWidget(pbtnSave, ++row, col);
    gLayout->addWidget(cbboxCamList, ++row, col);
    gLayout->addWidget(cbboxCamBrand, ++row, col);
    gLayout->addWidget(spboxOffX, ++row, col);
    gLayout->addWidget(spboxOffY, ++row, col);
    gLayout->addWidget(spboxWidth, ++row, col);
    gLayout->addWidget(spboxHeight, ++row, col);
    gLayout->addWidget(chkboxReverseY, ++row, col);
    gLayout->addWidget(cbboxFrameTrigMode, ++row, col);
    gLayout->addWidget(spboxFrameTrigDelay, ++(++row), col);
    gLayout->addWidget(cbboxExpMode, ++row, col);
    gLayout->addWidget(dspboxExp, ++row, col);
    gLayout->addWidget(cbboxGainMode, ++row, col);
    gLayout->addWidget(dspboxGain, ++row, col);
    gLayout->addWidget(dspboxRate, ++(++row), col);
    gLayout->addWidget(cbboxWbMode, ++row, col);
    gLayout->addWidget(spboxWBR, ++row, col);
    gLayout->addWidget(spboxWBG, ++row, col);
    gLayout->addWidget(spboxWBB, ++row, col);
    gLayout->addWidget(cbboxLineTrigMode, ++row, col);
    gLayout->addWidget(spboxPreDiv, ++row, col);
    gLayout->addWidget(spboxMul, ++row, col);
    gLayout->addWidget(spboxPostDiv, ++row, col);

    pbtnFrameSoftTrig->setVisible(false);
    lblFrameTrigDelay->setVisible(false);
    spboxFrameTrigDelay->setVisible(false);
    lblRate->setVisible(false);
    dspboxRate->setVisible(false);
    //默认黑白相机。隐藏彩色相机设置
    lblWbMode->setVisible(false);
    lblWBR->setVisible(false);
    lblWBG->setVisible(false);
    lblWBB->setVisible(false);
    cbboxWbMode->setVisible(false);
    spboxWBR->setVisible(false);
    spboxWBG->setVisible(false);
    spboxWBB->setVisible(false);
    //默认面阵相机，隐藏线阵相机设置
    lblLineTrigMode->setVisible(false);
    cbboxLineTrigMode->setVisible(false);
    lblPreDiv->setVisible(false);
    lblMul->setVisible(false);
    lblPostDiv->setVisible(false);
    spboxPreDiv->setVisible(false);
    spboxMul->setVisible(false);
    spboxPostDiv->setVisible(false);

}

void CameraManageWidget::initConnection()
{
    connect(cbboxFrameTrigMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](const int& index){
        lblFrameTrigDelay->setVisible(index > CameraTriggerType::CTT_Off);
        spboxFrameTrigDelay->setVisible(index > CameraTriggerType::CTT_Off);
        pbtnFrameSoftTrig->setVisible(index == CameraTriggerType::CTT_Software);
    });
    connect(cbboxWbMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](const int& index){
        lblWBR->setVisible(index == 0);
        lblWBG->setVisible(index == 0);
        lblWBB->setVisible(index == 0);
        spboxWBR->setVisible(index == 0);
        spboxWBG->setVisible(index == 0);
        spboxWBB->setVisible(index == 0);
    });
    connect(cbboxExpMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](const int& index){
        lblExp->setVisible(index == 0);
        dspboxExp->setVisible(index == 0);
    });
    connect(cbboxGainMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](const int& index){
        lblGain->setVisible(index == 0);
        dspboxGain->setVisible(index == 0);
    });
    connect(chkboxRateControl, &QCheckBox::stateChanged, this, [&](const int& state){
        lblRate->setVisible(state);
        dspboxRate->setVisible(state);
    });
    connect(cbboxCamList, &QComboBox::currentTextChanged, this, [&](const QString& name){
        emit sigReadCamParam(name);
    });
    connect(pbtnAdd, &QAbstractButton::clicked, this, [&](){
        QString brand = QInputDialog::getItem(this, "选择相机品牌", "相机品牌", CameraBase::mapCameraBrand.values(), 0, false);
        QString name = QInputDialog::getText(this,"输入新增通信名称","名称");
        if(name == "" || mMapCam.contains(name))
            return;
        CameraConfig config = getConfigFromUI();
        config.name = name;
        config.brand = CameraBrand(CameraBase::mapCameraBrand.values().indexOf(brand));
        cbboxCamBrand->setCurrentText(CameraBase::mapCameraBrand.value(config.brand));
        emit sigAddOne(config);
    });
    connect(pbtnDelete, &QAbstractButton::clicked, this, [&](){
        if(!(cbboxCamList->count() > 0))
            return;
        QMessageBox msgBox(QMessageBox::Question, "提示","确认删除此通信吗?",
                           QMessageBox::Yes | QMessageBox::No);
        msgBox.button(QMessageBox::Yes)->setText("确认");
        msgBox.button(QMessageBox::No)->setText("取消");
        if(QMessageBox::No == msgBox.exec())
            return;
        mMapCam.remove(cbboxCamList->currentText());
        emit sigDeleteOne(cbboxCamList->currentText());
        cbboxCamList->removeItem(cbboxCamList->currentIndex());
    });
    connect(pbtnSave, &QAbstractButton::clicked, this, [&](){
        if(!(cbboxCamList->count() > 0))
            return;
        CameraConfig config = getConfigFromUI();
        emit sigConfigChanged(config);
    });
    connect(pbtnRead, &QAbstractButton::clicked, this, [&](){
        if(!(cbboxCamList->count() > 0))
            return;
        emit sigReadCamParam(cbboxCamList->currentText());
    });
    connect(pbtnFrameSoftTrig, &QAbstractButton::clicked, this, [&](){
        if(!(cbboxCamList->count() > 0))
            return;
        emit sigFrameSoftTrig(cbboxCamList->currentText());
    });

}

void CameraManageWidget::checkCamType(const CameraConfig& config)
{
    bool isLine = config.isLine;
    lblLineTrigMode->setVisible(isLine);
    cbboxLineTrigMode->setVisible(isLine);
    lblPreDiv->setVisible(isLine);
    lblMul->setVisible(isLine);
    lblPostDiv->setVisible(isLine);
    spboxPreDiv->setVisible(isLine);
    spboxMul->setVisible(isLine);
    spboxPostDiv->setVisible(isLine);

    if(isLine){
        cbboxLineTrigMode->setCurrentIndex(config.trig.frameMode);
        QtUtils::configValueBox(spboxPreDiv, config.fc.preDiv.min, config.fc.preDiv.max, config.fc.preDiv.inc, config.fc.preDiv.val);
        QtUtils::configValueBox(spboxMul, config.fc.mul.min, config.fc.mul.max, config.fc.mul.inc, config.fc.mul.val);
        QtUtils::configValueBox(spboxPostDiv, config.fc.postDiv.min, config.fc.postDiv.max, config.fc.postDiv.inc, config.fc.postDiv.val);
    }
}

void CameraManageWidget::checkCamColor(const CameraConfig& config)
{
    bool isColor = config.isColor;
    lblWbMode->setVisible(isColor);
    cbboxWbMode->setVisible(isColor);
    lblWBR->setVisible(isColor && cbboxWbMode->currentIndex() == 0);
    lblWBG->setVisible(isColor && cbboxWbMode->currentIndex() == 0);
    lblWBB->setVisible(isColor && cbboxWbMode->currentIndex() == 0);
    spboxWBR->setVisible(isColor && cbboxWbMode->currentIndex() == 0);
    spboxWBG->setVisible(isColor && cbboxWbMode->currentIndex() == 0);
    spboxWBB->setVisible(isColor && cbboxWbMode->currentIndex() == 0);

    if(isColor){
        cbboxWbMode->setCurrentIndex(config.wb.wbMode);
        if(config.wb.wbMode == 0){
            QtUtils::configValueBox(spboxWBR, config.wb.wbR.min, config.wb.wbR.max, config.wb.wbR.inc, config.wb.wbR.val);
            QtUtils::configValueBox(spboxWBG, config.wb.wbG.min, config.wb.wbG.max, config.wb.wbG.inc, config.wb.wbG.val);
            QtUtils::configValueBox(spboxWBB, config.wb.wbB.min, config.wb.wbB.max, config.wb.wbB.inc, config.wb.wbB.val);
        }
    }

}

CameraConfig CameraManageWidget::getConfigFromUI()
{
    CameraConfig config;

    config.name = cbboxCamList->currentText();
    config.brand = CameraBrand(cbboxCamBrand->currentIndex());

    CameraTrigger trig;
    trig.frameMode = CameraTriggerType(cbboxFrameTrigMode->currentIndex());
    trig.frameDelay.val = spboxFrameTrigDelay->value();
    trig.lineMode = CameraTriggerType(cbboxLineTrigMode->currentIndex());

    CameraBrightness bright;
    bright.expMode = cbboxExpMode->currentIndex();
    bright.gainMode = cbboxGainMode->currentIndex();
    bright.exp.val = dspboxExp->value();
    bright.gain.val = dspboxGain->value();

    CameraFrameRate rate;
    rate.rateControl = chkboxRateControl->isChecked();
    rate.rate.val = dspboxRate->value();

    CameraROI roi;
    roi.offX.val = spboxOffX->value();
    roi.offY.val = spboxOffY->value();
    roi.width.val = spboxWidth->value();
    roi.height.val = spboxHeight->value();

    CameraTrans trans;
    trans.reverseX = chkboxReverseX->isChecked();
    trans.reverseY = chkboxReverseY->isChecked();

    CameraWhiteBalance wb;
    wb.wbMode = cbboxWbMode->currentIndex();
    wb.wbR.val = spboxWBR->value();
    wb.wbG.val = spboxWBG->value();
    wb.wbB.val = spboxWBB->value();

    FrequencyConverter fc;
    fc.preDiv.val = spboxPreDiv->value();
    fc.mul.val = spboxMul->value();
    fc.postDiv.val = spboxPostDiv->value();

    config.trig = trig;
    config.bright = bright;
    config.rate = rate;
    config.roi = roi;
    config.trans = trans;
    config.wb = wb;
    config.fc = fc;

    return config;
}

